package de.koller.worlders.engine.tiles.light;

import de.koller.oceanFramework.gl.util.FrameTexture;
import de.koller.oceanFramework.gl.util.ParticleTexture;
import de.koller.oceanFramework.gl.util.RasterManager;
import de.koller.oceanFramework.gl.util.ViewUtil;
import de.koller.oceanFramework.tree.Child;
import de.koller.worlders.WSea;
import de.koller.worlders.WorldersRoot;
import de.koller.worlders.engine.tiles.MapRendering;
import de.koller.worlders.engine.tiles.light.lights.IOverlayLight;
import de.koller.worlders.engine.tiles.light.lights.OLightContainer;
import de.koller.worlders.engine.util.thread.ResourceLoader;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;

public class Light extends WSea {

	@Child private final OLightContainer olightContainer = new OLightContainer();
	
	private boolean useDebugLight = false;
	private int ax, ay;
	@Child private final LightContainer container = new LightContainer();
	private ParticleTexture lightmap;
	private FrameTexture lightframe;
	
	private final ResourceLoader lightThread = new ResourceLoader( container );
	
	private RasterManager tmpLightRaster;
//	private ParticleTexture lightbulb;
	
	public int debugLightCalcTime = 0;
	
	@Override
	protected void init() {
		super.init();
		
//		lightframe = FrameTexture.generate( WorldersRoot.D_WIDTH, WorldersRoot.D_HEIGHT );
		lightframe = FrameTexture.generate( 1024, 1024 );
		ParticleTexture.MAG_FILTER = GL11.GL_LINEAR;
		lightmap = ParticleTexture.generate( MapRendering.SCREEN_TILES + MapRendering.SCREEN_TILES_OFF*2, 
											 MapRendering.SCREEN_TILES + MapRendering.SCREEN_TILES_OFF*2 );
		
		lightThread.startResource();
//		lightthread.startCalculateAsync();
		
//		lightbulb = ParticleTexture.generate( 512, 512 );
//		lightbulb.clear( 0xff000000 );
//		for( int x = 0; x < 500; x++ )
//			for( int y = 0; y < 500; y++ ) {
//				double v = Point.distance( 256, 256, x, y );
//				int c = (int)((1d - v/200d) * 255d);
//				if( c < 0 ) c = 0;
//				lightbulb.setPixel( ColorIntUtil.getIntColor( 0xff, c, c, c ), x, y );
//			}
//		lightbulb.flush();
	}

	public void remove( IOverlayLight light ) {
		olightContainer.remove( light );
	}

	public void add( IOverlayLight light ) {
		olightContainer.add( light );
	}
	
	@Override
	protected void update( int elapsedTime ) {
		super.update( elapsedTime );
		
		if( wroot.getInput().isKeyPressed( Keyboard.KEY_L ) ) {
			useDebugLight = !useDebugLight;
			
		}
	}
	
	public LightSource addLightSource( int x, int y, int light ) {
		return container.addLightSource( x, y, light );
	}
	
	public void removeLightSource( LightSource lsource ) {
		container.removeLightSource( lsource );
	}
	
	public void renderLight() {
		if( wroot.getDebug().isActive() && wroot.getDebug().isBuild() && !useDebugLight )
			return;
		
		updateFBO();
		
		GL11.glEnable( GL11.GL_BLEND );
		GL11.glBlendFunc( GL11.GL_DST_COLOR, GL11.GL_ZERO );
		GL11.glColor3f( 1, 1, 1 );
		
//		GL11.glPopMatrix();
		ViewUtil.draw2D( lightframe.getTexture(), 0, 0, WorldersRoot.D_WIDTH, WorldersRoot.D_HEIGHT, 2, 0, 1, 1, 0 );
//		wroot.rendering.glScaleToCamera();
		
//		lightmap.bind();
		
		GL11.glDisable( GL11.GL_BLEND );
	}

	private void updateFBO() {
		wroot.rendering.viewportGL.unbind();
		lightframe.bindFBO();
		
		boolean stencilsafe = GL11.glGetBoolean( GL11.GL_STENCIL_TEST );
		GL11.glDisable( GL11.GL_STENCIL_TEST );
		
		GL11.glClearColor( 0f, 0f, 0f, 1f );
		GL11.glClear( GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT );
		
		wroot.rendering.worlderV.setTransform();
		updateLightMap();
		lightmap.draw2D( ax, ay, MapRendering.SCREEN_TILES + MapRendering.SCREEN_TILES_OFF * 2, 
				MapRendering.SCREEN_TILES + MapRendering.SCREEN_TILES_OFF * 2, 0 );
		
		GL11.glEnable( GL11.GL_BLEND );
		GL11.glBlendFunc( GL11.GL_DST_ALPHA, GL11.GL_ONE_MINUS_DST_ALPHA );
		
		int be = GL11.glGetInteger( GL14.GL_BLEND_EQUATION );
		GL14.glBlendEquation( GL14.GL_MAX );
		
		GL11.glColor3f( 1, 1, 1 );
		olightContainer.renderLightsNow();
		
		wroot.rendering.worlderV.unsetTransform();
		
		GL11.glColor3f( 1, 1, 1 );
		GL14.glBlendEquation( be );
		
		GL11.glDisable( GL11.GL_BLEND );
		
		if( stencilsafe )
			GL11.glEnable( GL11.GL_STENCIL_TEST );
		
		lightframe.unbindFBO();
		wroot.rendering.viewportGL.rebind();
	}
	
	private void updateLightMap() {
		debugLightCalcTime++;
		
		if( !container.isRdy() )
			return;
	
		lightThread.finishResource();
		
		final int rw = MapRendering.SCREEN_TILES + MapRendering.SCREEN_TILES_OFF*2,
				  rh = MapRendering.SCREEN_TILES + MapRendering.SCREEN_TILES_OFF*2;
		int ox = -(int)Math.floor( wroot.getTileMap().getOffsetX() ) - (int)(MapRendering.SCREEN_TILES_OFF );
		int oy = -(int)Math.floor( wroot.getTileMap().getOffsetY() ) - (int)(MapRendering.SCREEN_TILES_OFF );
		ax = ox; ay = oy;
		
		if( tmpLightRaster == null ) {
			tmpLightRaster = new RasterManager( rw, rh );
			container.clearBuffer( ox, oy, rw, rh );
		}
		
		lightmap.bind();
	
		for( int x = 0; x < rw; x++ )
			for( int y = 0; y < rh; y++ ) {
				int lc = container.getLight( ox + x, oy + y );
				//lightmap.setPixel( lc, x, y );
				tmpLightRaster.setPixel( lc, x, y );
			}
		
		lightmap.flush( 0, 0, rw, rh, tmpLightRaster.getData() );

//		lightmap.flush();
		debugLightCalcTime = 0;
		container.clearBuffer( ox, oy, rw, rh );
		lightThread.startResource();
	}

	public int getLightSourcesNumber() {
		return container.getLightSourcesNumber();
	}

}
